import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'dart:math' as math;
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';

/// 速度码表小部件
class SpeedometerView extends StatefulWidget {
  /// 当前速度值
  final RxDouble speed;

  /// 最大速度值
  final RxDouble maxSpeed;

  /// 速度单位
  final RxString unit;

  /// 表盘大小
  final double size;

  /// 边框背景色
  final Color borderColor;

  /// 表盘背景色
  final Color backgroundColor;

  /// 表盘前景色
  final Color foregroundColor;

  /// 指针颜色
  final Color pointerColor;

  /// 数值文本颜色
  final Color textColor;

  /// 刻度颜色
  final Color divisionsColor;

  /// 刻度文本颜色
  final Color divisionsTextColor;

  /// 刻度数量
  final int divisions;

  /// 动画持续时间
  final Duration animationDuration;

  const SpeedometerView({
    Key? key,
    required this.speed,
    required this.maxSpeed,
    required this.unit,
    this.size = 240,
    this.borderColor = const Color(0xFF0088FF),
    this.backgroundColor = Colors.transparent,
    this.foregroundColor = const Color(0xFF0088FF),
    this.divisionsColor = const Color(0xFFF1F1F1),
    this.divisionsTextColor = const Color(0xFF000000),
    this.pointerColor = Colors.red,
    this.textColor = Colors.black,
    this.divisions = 10,
    this.animationDuration = const Duration(milliseconds: 500),
  })  : assert(speed >= 0, 'Speed must be non-negative'),
        assert(maxSpeed > 0, 'Max speed must be positive'),
        super(key: key);

  @override
  State<SpeedometerView> createState() => _SpeedometerViewState();
}

class _SpeedometerViewState extends State<SpeedometerView>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _speedAnimation;
  late RxDouble _currentSpeed;
  late Worker _speedWorker;

  @override
  void initState() {
    super.initState();
    _currentSpeed = RxDouble(widget.speed.value);
    _animationController = AnimationController(
      vsync: this,
      duration: widget.animationDuration,
    );

    // Setup the animation
    _setupAnimation(widget.speed.value);

    // Listen to changes in the widget.speed reactive variable
    _speedWorker = ever(widget.speed, (double newSpeed) {
      if (_animationController.isAnimating) {
        _animationController.stop();
      }
      _setupAnimation(newSpeed);
      _animationController.forward(from: 0.0);
    });
  }

  void _setupAnimation(double targetSpeed) {
    _speedAnimation = Tween<double>(
      begin: _currentSpeed.value,
      end: targetSpeed,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    ))
      ..addListener(() {
        _currentSpeed.value = _speedAnimation.value;
      });
  }

  @override
  void dispose() {
    _speedWorker.dispose();
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: widget.size,
      height: widget.size,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Obx(() {
            return CustomPaint(
              size: Size(widget.size, widget.size),
              painter: _SpeedometerPainter(
                speed: _currentSpeed.value,
                maxSpeed: widget.maxSpeed.value,
                borderColor: widget.borderColor,
                backgroundColor: widget.backgroundColor,
                foregroundColor: widget.foregroundColor,
                pointerColor: widget.pointerColor,
                divisions: widget.divisions,
                divisionsColor: widget.divisionsColor,
                divisionsTextColor: widget.divisionsTextColor,
              ),
            );
          }),

          // 速度数值显示
          Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Obx(
                  () => Text(
                    _currentSpeed.value.toStringAsFixed(0),
                    style: TextStyle(
                      fontSize: 100.w,
                      fontWeight: FontWeight.w700,
                      color: widget.textColor,
                    ),
                  ),
                ),
                Obx(
                  () => Text(
                    widget.unit.value,
                    style: TextStyle(
                      fontSize: 28.w,
                      fontWeight: FontWeight.w700,
                      color: widget.textColor,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _SpeedometerPainter extends CustomPainter {
  final double speed;
  final double maxSpeed;
  final Color borderColor;
  final Color backgroundColor;
  final Color foregroundColor;
  final Color pointerColor;
  final Color divisionsColor;
  final Color divisionsTextColor;
  final int divisions;

  _SpeedometerPainter({
    required this.speed,
    required this.maxSpeed,
    required this.borderColor,
    required this.backgroundColor,
    required this.foregroundColor,
    required this.pointerColor,
    required this.divisionsColor,
    required this.divisionsTextColor,
    required this.divisions,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = size.width / 2;

    double u = 0.17;
    // 绘制边框圆弧
    final borderPaint = Paint()
      ..shader = SweepGradient(
        colors: [
          borderColor.withOpacity(0),
          borderColor,
          borderColor.withOpacity(0),
        ],
        stops: [0.0, (1 - 2 * u) / 2, (1 - 2 * u)],
        startAngle: 0.0,
        endAngle: math.pi * 2,
        transform: GradientRotation(math.pi * (1 - u)), // 旋转渐变以匹配弧形起始位置
      ).createShader(Rect.fromCircle(center: center, radius: radius * 0.95))
      ..style = PaintingStyle.stroke
      ..strokeWidth = radius * 0.03
      ..strokeCap = StrokeCap.round;

    // 仪表盘范围是240度，从-120度到120度
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius * 0.95),
      math.pi * (1 - u), // 开始于150度(2.5π/3)
      math.pi * (1 - u + 1.5), // 扫过240度(4π/3)
      false,
      borderPaint,
    );

    // 绘制背景圆
    final bgPaint = Paint()
      ..shader = LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [borderColor.withOpacity(0.1), borderColor.withOpacity(0)],
        stops: const [
          0.0,
          0.85
        ], // Start transition higher to create 20px offset from bottom
      ).createShader(Rect.fromCircle(center: center, radius: radius * 0.95))
      ..style = PaintingStyle.fill;

    // 整个圆
    canvas.drawCircle(
      center,
      radius * 0.95,
      bgPaint,
    );

    // 绘制背景圆弧
    final progressBackgoundPaint = Paint()
      ..color = backgroundColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = radius * 0.1
      ..strokeCap = StrokeCap.round;

    // 仪表盘范围是240度，从-120度到120度
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius * 0.8),
      math.pi * 0.83, // 开始于150度(2.5π/3)
      math.pi * 1.33, // 扫过240度(4π/3)
      false,
      progressBackgoundPaint,
    );

    // 绘制刻度
    _drawDivisions(canvas, center, radius);

    // 绘制进度圆弧
    final progressPaint = Paint()
      ..color = foregroundColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = radius * 0.1
      ..strokeCap = StrokeCap.butt;

    final progressAngle = math.min(speed / maxSpeed, 1.0) * math.pi * 1.33;

    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius * 0.8),
      math.pi * 0.83,
      progressAngle,
      false,
      progressPaint,
    );

    // 绘制指针
    _drawPointer(canvas, center, radius);
  }

  void _drawDivisions(Canvas canvas, Offset center, double radius) {
    final paint = Paint()
      ..color = divisionsColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    for (int i = 0; i <= divisions; i++) {
      final angle = math.pi * 0.83 + (i / divisions) * math.pi * 1.33;
      final outer = Offset(
        center.dx + (radius * 0.85) * math.cos(angle),
        center.dy + (radius * 0.85) * math.sin(angle),
      );
      final inner = Offset(
        center.dx + (radius * 0.75) * math.cos(angle),
        center.dy + (radius * 0.75) * math.sin(angle),
      );

      canvas.drawLine(inner, outer, paint);

      // 绘制刻度值
      if (i % 2 == 0) {
        final textPainter = TextPainter(
          text: TextSpan(
            text: (i * maxSpeed / divisions).toStringAsFixed(0),
            style: TextStyle(
              color: divisionsTextColor,
              fontSize: radius * 0.08,
            ),
          ),
          textDirection: TextDirection.ltr,
        );

        textPainter.layout();

        final textPosition = Offset(
          center.dx + (radius * 0.65) * math.cos(angle) - textPainter.width / 2,
          center.dy +
              (radius * 0.65) * math.sin(angle) -
              textPainter.height / 2,
        );

        textPainter.paint(canvas, textPosition);
      }
    }
  }

  // 绘制指针
  void _drawPointer(Canvas canvas, Offset center, double radius) {
    final angle =
        math.pi * 0.83 + math.min(speed / maxSpeed, 1.0) * math.pi * 1.33;

    final pointerEnd = Offset(
      center.dx + (radius * 0.7) * math.cos(angle),
      center.dy + (radius * 0.7) * math.sin(angle),
    );

    // 绘制指针扫过的区域（颜色填充扇形）
    final sweepPaint = Paint()
      ..shader = RadialGradient(
        colors: [
          pointerColor.withOpacity(0.04),
          pointerColor.withOpacity(0.04),
        ],
      ).createShader(Rect.fromCircle(center: center, radius: radius))
      ..style = PaintingStyle.fill;

    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius * 0.7),
      math.pi * 0.83,
      angle - math.pi * 0.83,
      true,
      sweepPaint,
    );

    // 绘制指针线 - 使用渐变色，越靠近圆心颜色越浅
    final pointerPaint = Paint()
      ..shader = LinearGradient(
        begin: Alignment.centerLeft,
        end: Alignment.centerRight,
        colors: [
          pointerColor.withOpacity(0.1),
          pointerColor,
        ],
        transform: GradientRotation(angle), // 旋转渐变以匹配指针角度
      ).createShader(Rect.fromPoints(center, pointerEnd))
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3.0
      ..strokeCap = StrokeCap.round;

    canvas.drawLine(center, pointerEnd, pointerPaint);

    // 绘制中心圆点
    final centerPaint = Paint()
      ..color = pointerColor.withOpacity(0.1)
      ..style = PaintingStyle.fill;

    canvas.drawCircle(center, radius * 0.05, centerPaint);
  }

  @override
  bool shouldRepaint(covariant _SpeedometerPainter oldDelegate) {
    return oldDelegate.speed != speed ||
        oldDelegate.maxSpeed != maxSpeed ||
        oldDelegate.backgroundColor != backgroundColor ||
        oldDelegate.foregroundColor != foregroundColor ||
        oldDelegate.pointerColor != pointerColor;
  }
}
